﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using FileSystem.Models;
using FileSystem.Services.IServices;
using SQLite;

namespace FileSystem.Services.Realization {
    /// <summary>
    /// 访问控制信息存储
    /// </summary>
    public class AccessControlInfoStorage : IAccessControlInfoStorage {
        // ******** 公开变量

        /// <summary>
        /// AccessControlInfoTable文件路径
        /// </summary>
        public static readonly string DbPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder
                .LocalApplicationData), DbName);

        /// <summary>
        /// AccessControlInfoTable数据库连接
        /// </summary>
        private SQLiteAsyncConnection _connection;

        public SQLiteAsyncConnection Connection =>
            _connection ?? (_connection = new SQLiteAsyncConnection(DbPath));

        // ******** 私有变量

        /// <summary>
        /// TableDb文件名
        /// </summary>
        private const string DbName = "AccessControlInfoTable.sqlite3";

        /// <summary>
        /// 偏好存储服务
        /// </summary>
        private IPreferenceStorage _preferenceStorage;

        // ******** 继承方法

        /// <summary>
        /// 初始化访问控制信息存储
        /// </summary>
        public async Task InitializeAsync() {
            // AccessControlInfoTable.sqlite3 文件初始化
            await Connection.CreateTableAsync<AccessControlInfo>();

            _preferenceStorage.Set(AccessControlInfoStorageConstants.VersionKey,
                AccessControlInfoStorageConstants.Version);
        }

        /// <summary>
        /// 访问控制信息存储是否已经初始化
        /// </summary>
        public bool IsInitialized() {
            return _preferenceStorage.Get(
                    AccessControlInfoStorageConstants.VersionKey,
                    AccessControlInfoStorageConstants.DefaultVersion) ==
                AccessControlInfoStorageConstants.Version;
        }

        /// <summary>
        /// 增加访问控制信息
        /// </summary>
        /// <param name="accessControlInfo">要添加的访问控制信息</param>
        public async Task AddAsync(AccessControlInfo accessControlInfo) {
            await Connection.InsertAsync(accessControlInfo);
        }

        /// <summary>
        /// 删除访问控制信息
        /// </summary>
        /// <param name="accessControlInfo">要删除的访问控制信息</param>
        public async Task RemoveAsync(AccessControlInfo accessControlInfo) {
            await Connection.DeleteAsync(accessControlInfo);
        }

        /// <summary>
        /// 修改属性
        /// </summary>
        /// <param name="accessControlInfo">访问控制信息</param>
        /// <param name="property">属性</param>
        /// <param name="newContent">新值</param>
        public async Task ModifyProperty(AccessControlInfo accessControlInfo,
            AccessControlInfoConst.Property property, string newContent) {
            switch (property) {
                case AccessControlInfoConst.Property.DirItemName: {
                    accessControlInfo.DirItemName = newContent;
                    await Connection.InsertOrReplaceAsync(accessControlInfo);
                    break;
                }
                case AccessControlInfoConst.Property.Location: {
                    accessControlInfo.Location = newContent;
                    await Connection.InsertOrReplaceAsync(accessControlInfo);
                    break;
                }
                case AccessControlInfoConst.Property.UserName: {
                    accessControlInfo.UserName = newContent;
                    await Connection.InsertOrReplaceAsync(accessControlInfo);
                    break;
                }
            }
        }

        /// <summary>
        /// 修改属性
        /// </summary>
        /// <param name="accessControlInfo">访问控制信息</param>
        /// <param name="property">属性</param>
        /// <param name="newContent">新值</param>
        public async Task ModifyProperty(AccessControlInfo accessControlInfo,
            AccessControlInfoConst.Property property, bool newContent) {
            switch (property) {
                case AccessControlInfoConst.Property.Readable: {
                    accessControlInfo.Readable = newContent;
                    await Connection.InsertOrReplaceAsync(accessControlInfo);
                    break;
                }
                case AccessControlInfoConst.Property.Writable: {
                    accessControlInfo.Writable = newContent;
                    await Connection.InsertOrReplaceAsync(accessControlInfo);
                    break;
                }
                case AccessControlInfoConst.Property.Deletable: {
                    accessControlInfo.Deletable = newContent;
                    await Connection.InsertOrReplaceAsync(accessControlInfo);
                    break;
                }
            }
        }

        /// <summary>
        /// 根据目录项名、路径和用户名获得用户对该目录项的访问控制信息
        /// </summary>
        /// <param name="dirItemName">目录项名</param>
        /// <param name="location">路径</param>
        /// <param name="userName">用户名</param>
        public async Task<AccessControlInfo> GetAccessControlInfo(
            string dirItemName, string location, string userName) {
            return await Connection.Table<AccessControlInfo>()
                .FirstOrDefaultAsync(p =>
                    p.DirItemName == dirItemName && p.Location == location &&
                    p.UserName == userName);
        }

        /// <summary>
        /// 获得所有访问控制信息
        /// </summary>]
        public async Task<IList<AccessControlInfo>> GetAccessControlInfos() {
            return await Connection.Table<AccessControlInfo>().ToListAsync();
        }

        // ******** 公开方法

        /// <summary>
        /// 访问控制信息存储
        /// </summary>
        public AccessControlInfoStorage(IPreferenceStorage preferenceStorage) {
            _preferenceStorage = preferenceStorage;
        }

        /// <summary>
        /// 关闭数据库
        /// </summary>
        public async Task CloseAsync() {
            await Connection.CloseAsync();
        }

        // ******** 私有方法
    }
}